/****************************************************
*	OSMF Edge Media Player version 1.2.0
* 
*	Author: Emanuele Manco
* 	E-Mail: hello@flashedge.net
*	Web: http://activeden.net/user/flashedge
*  
*****************************************************/

package net.flashedge.core
{
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.system.Security;
	import flash.text.Font;
	import org.osmf.traits.MediaTraitType;
	import org.osmf.traits.TimeTrait;
	
	import org.osmf.containers.MediaContainer;
	import org.osmf.elements.AudioElement;
	import org.osmf.elements.F4MElement;
	import org.osmf.elements.ImageElement;
	import org.osmf.elements.ProxyElement;
	import org.osmf.events.LoaderEvent;
	import org.osmf.events.MediaErrorEvent;
	import org.osmf.events.MediaFactoryEvent;
	import org.osmf.media.MediaElement;
	import org.osmf.media.MediaResourceBase;
	import org.osmf.metadata.Metadata;
	import org.osmf.traits.LoadState;
	
	import org.osmf.elements.VideoElement;
	import org.osmf.events.TimeEvent;
	import org.osmf.events.LoadEvent;
	import org.osmf.events.PlayEvent;
	import org.osmf.traits.PlayState;
	import org.osmf.events.BufferEvent;
	import org.osmf.events.MediaPlayerStateChangeEvent;
	import org.osmf.media.MediaPlayerSprite;
	import org.osmf.media.URLResource;
	import org.osmf.layout.ScaleMode;
	
	// vast classes
	import org.osmf.vast.loader.VASTLoadTrait;
	import org.osmf.vast.loader.VASTLoader;
	import org.osmf.vast.media.CompanionElement;
	import org.osmf.vast.media.VASTMediaGenerator;
	
	import org.osmf.vast.media.VAST2ImpressionProxyElement;
	import org.osmf.vast.media.VASTImpressionProxyElement;
	import org.osmf.youtube.elements.YouTubeElement;
	
	
	//[SWF(width='680', height='382', backgroundColor='#000000', frameRate='30')]	// not needed for now
	
	public class MediaPlayer extends Sprite
	{
		// Video sources for testing
		/*public static const LOGO_VID:String = "http://mediapm.edgesuite.net/osmf/content/test/logo_animated.flv";
		public static const PROGRESSIVE_PATH:String = "http://mediapm.edgesuite.net/strobe/content/test/AFaerysTale_sylviaApostol_640_500_short.flv";
		public static const STREAMING_PATH:String = "rtmp://cp67126.edgefcs.net/ondemand/mediapm/osmf/content/test/akamai_10_year_f8_512K";
		public static const STREAMING_MP4_PATH:String = "rtmp://cp67126.edgefcs.net/ondemand/mp4:mediapm/ovp/content/demo/video/elephants_dream/elephants_dream_768x428_24.0fps_408kbps.mp4";
		public static const LOCAL_SWF:String = "assets/swf_banner.swf";
		public static const DYNAMIC_STREAMING:String = "http://mediapm.edgesuite.net/osmf/content/test/manifest-files/dynamic_Streaming.f4m";*/
	
		//public static const CONTENT_VIDEO:String	= "rtmp://cp67126.edgefcs.net/ondemand/mediapm/strobe/content/test/SpaceAloneHD_sounas_640_500_short";
		
		
		// vast vars
		private var vastLoader:VASTLoader;
		private var vastLoadTrait:VASTLoadTrait;
		private var vastMediaGenerator:VASTMediaGenerator;
		
		public static const MAX_NUMBER_REDIRECTS:int 		= 5;
		public static const chosenPlacement:String = VASTMediaGenerator.PLACEMENT_LINEAR;
		
		// Vast assets for testing
		/*public static const INVALID_VAST:String 						= "http://cdn1.eyewonder.com/200125/instream/osmf/invalid_vast.xml";
		public static const VAST_1_LINEAR_FLV:String 					= "http://cdn1.eyewonder.com/200125/instream/osmf/vast_1_linear_flv.xml";
		public static const VAST_1_WRAPPER:String 						= "http://cdn1.eyewonder.com/200125/instream/osmf/vast_1_wrapper.xml";
		public static const VAST_2_BROKEN_FLV:String 					= "http://cdn1.eyewonder.com/200125/instream/osmf/vast_2_broken_flv.xml";
		public static const VAST_2_BROKEN_VPAID:String 					= "http://cdn1.eyewonder.com/200125/instream/osmf/vast_2_broken_vpaid.xml";
		public static const VAST_2_ENDLESS_WRAPPER:String 				= "http://cdn1.eyewonder.com/200125/instream/osmf/vast_2_endless_wrapper.xml";
		public static const VAST_2_LINEAR_FLV_NONLINEAR_VPAID:String 	= "http://cdn1.eyewonder.com/200125/instream/osmf/vast_2_linear_flv_nonlinear_vpaid.xml";
		public static const VAST_2_LINEAR_VPAID:String 					= "http://cdn1.eyewonder.com/200125/instream/osmf/vast_2_linear_vpaid.xml";
		public static const VAST_2_LINEAR_VPAID_TRACKING_TEST:String 	= "http://cdn1.eyewonder.com/200125/instream/osmf/vast_2_linear_vpaid_tracking_test.xml";
		public static const VAST_2_NONLINEAR_VPAID:String 				= "http://cdn1.eyewonder.com/200125/instream/osmf/vast_2_nonlinear_vpaid.xml";
		public static const VAST_2_WRAPPER:String 						= "http://cdn1.eyewonder.com/200125/instream/osmf/vast_2_wrapper.xml";
		
		public static const chosenFile:String =  VAST_2_LINEAR_FLV_NONLINEAR_VPAID;	// */
		
		public var youtubeReady:Boolean = false;
		public var element;
		public var path:String;
		public var videoID:String;
		public var publisherID:String;
		public var displayName:String;
		
		public var w:Number;
		public var h:Number;
		public var fluidMode:Boolean = true;
		
		public var mps:MediaPlayerSprite;
		
		public var playing:Boolean;
		public var buffering:Boolean;
		public var status:String;
		public var state:String;
		public var loadState:String;
		
		public var tubemogulEnabled:Boolean = false;
		
		static public const GTRACK_NAMESPACE:String = "http://www.realeyes.com/osmf/plugins/tracking/google";
		
		
		public function MediaPlayer()
		{
			//init();
		}
	
	// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	//																				INITIALIZE FUNCTION
	// _____________________________________________________________________________________________________________
		
		public function init():void
		{
			Security.allowDomain("www.youtube.com");
			
			stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
			
			mps = new MediaPlayerSprite();
			addChild(mps);
			
			// setup background
			mps.mediaContainer.backgroundAlpha = 1;
			mps.mediaContainer.backgroundColor = 0x000000;
			
			// setup size
			mps.width = 640;						// width
			mps.height = 360;						// height
			mps.scaleMode = ScaleMode.LETTERBOX;	// scale modes
			
			// setup initial volume
			mps.mediaPlayer.volume = 1;	
			
			addEventListeners();	// all event listeners
			
			//launch(CONTENT_VIDEO);	// launch the video!
		}
	
	// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	//																							LISTENERS
	// _____________________________________________________________________________________________________________
		
		private function addEventListeners():void
		
		{
			mps.addEventListener(MouseEvent.CLICK, onClick);
			
			mps.mediaPlayer.addEventListener(PlayEvent.PLAY_STATE_CHANGE, onPlayState);
			mps.mediaPlayer.addEventListener(BufferEvent.BUFFERING_CHANGE, bufferChange);
			mps.mediaPlayer.addEventListener(MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE, stateChange);
			
			mps.mediaPlayer.addEventListener(TimeEvent.CURRENT_TIME_CHANGE, onCurrentTimeChange);
			mps.mediaPlayer.addEventListener(LoadEvent.BYTES_LOADED_CHANGE, onLoadingBytesChange);
			mps.mediaPlayer.addEventListener(LoadEvent.LOAD_STATE_CHANGE, onLoadingStateChange);
			
			mps.mediaFactory.addEventListener(MediaFactoryEvent.PLUGIN_LOAD, onPluginLoaded);
			mps.mediaFactory.addEventListener(MediaFactoryEvent.PLUGIN_LOAD_ERROR, onPluginLoadFailed);
			
			mps.mediaPlayer.addEventListener ( TimeEvent.COMPLETE , onTimeComplete , false , 0 , true ) ;
		}
		
		private function onTimeComplete(e:TimeEvent):void 
		{
			trace ("Time has completed!");
			dispatchEvent(new Event("TimeCompleted"));
		}
		
		public function loadPlugin(id:String, path:String, config:XML = null, playerID:String = null, trackerID:String = null):void {
			
			var pluginResource:MediaResourceBase = new URLResource (path);
			
			switch (id) {
				case "gtrack": pluginResource.addMetadataValue(GTRACK_NAMESPACE, config );
				break;
				case "tubemogul":
				var TMParams:Object = {	  display: mps,
										  pl: mps.mediaPlayer,
										  playerID: playerID,
										  trackerIDs: trackerID,
										  videoURL: path,
										  publisherID: publisherID,
										  videoID: videoID,
										  displayName: displayName
										}
				pluginResource.addMetadataValue("TMParams", TMParams);
				tubemogulEnabled = true;
				break;
				case "mast":
				break;
				}
			if (id == "gtrack" && config) { pluginResource.addMetadataValue(GTRACK_NAMESPACE, config ); }
			
			mps.mediaFactory.loadPlugin( pluginResource );
			
			//mps.mediaFactory.loadPlugin( new URLResource(path));
		}
		
		private function onPluginLoadFailed(e:MediaFactoryEvent):void 
		{
			trace ("The plug-in didn't load! " +e.type);
			dispatchEvent(new Event("PluginError"));
		}
		
		private function onPluginLoaded(e:MediaFactoryEvent):void 
		{
			dispatchEvent(new Event("PluginLoaded"));
			trace ("Plugin loaded successfully.");
		}
		
	// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	//																			VIDEO LAUNCHING FUNCTION
	// _____________________________________________________________________________________________________________
	
		
		public function launch(path:String, type="video", id:String="12345", name="videoName", publisher="publisherName", category="categoryName"):void {

			var index:int = path.indexOf(".xml");	// check if it is a VAST xml file instead of a video source
			trace ("index is: " + index);
			
			if (index != -1 || type == "vast") {
				trace ("it's an xml file, probably for VAST.");
				// vast attempt
				var vastResource:URLResource = new URLResource(path);
				vastLoader = new VASTLoader(MAX_NUMBER_REDIRECTS);
				vastLoadTrait = new VASTLoadTrait(vastLoader, vastResource);
				vastLoader.addEventListener(LoaderEvent.LOAD_STATE_CHANGE, onVASTLoadStateChange);
				vastLoader.load(vastLoadTrait);
				
			} else {
				trace ("It's a normal media source, skipping VAST...");
				
				youtubeReady = false;
				mps.resource = new URLResource( path );
				
				var obj = mps.media;
			
					// check if we have the tubemogul plugin and add the metadata
					if (tubemogulEnabled) {
						var TMMediaParams:Object = {
						  publisherID:publisher,
						  videoID:id,
						  displayName:name,
						  categories:category
						}
						
						mps.media.resource.addMetadataValue("TMMediaParams", TMMediaParams); 	// metadata for tubemogul plugin
					}
					
				// check if there is a gtracking proxy and parse the element properly
				if ((mps.media is VideoElement) || (mps.media is ImageElement) || (mps.media is AudioElement) || (mps.media is YouTubeElement) || (mps.media is F4MElement) || (mps.media is ProxyElement)) {
					element = obj;
				} else {
					element = obj.proxiedElement;											// pass the proxied element from gtrack
					mps.resource.addMetadataValue (GTRACK_NAMESPACE, { pageURL: id } );		// metadata for gtrack plugin
					}
				
				setSmoothing(element);
				
			}
		}
		
		public function checkYoutube(element):Boolean
		{
			var result:Boolean;
			element is YouTubeElement ? result = true : result = false;
			
			return result;
		}
		
	// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	//																			VIDEO LAUNCHING FUNCTION
	// _____________________________________________________________________________________________________________
	
		private function onPlayState(e:PlayEvent):void 
		{
			switch(e.playState)
			 {
				case PlayState.PLAYING: trace ("Playing"); status = "playing";
				break;
		 
				case PlayState.PAUSED: trace ("Paused"); status = "paused";
				break;
		 
				case  PlayState.STOPPED: trace ("Stopped"); status = "stopped";
					
					/*if (mps.mediaContainer.hasEventListener(MouseEvent.MOUSE_UP)) {
						trace ("container was in button mode! Disabling...");
						mps.mediaContainer.buttonMode = false;
						mps.mediaContainer.removeEventListener(MouseEvent.MOUSE_UP, onMediaElementClick);
						function onMediaElementClick(e:MouseEvent):void {}
					}*/
				break;
			 }
			 
			 dispatchEvent(new Event("PlayChange"));
		}
		
		
		
		private function stateChange(e:MediaPlayerStateChangeEvent):void 
		{
			trace("Current status: " + e.state);
			state = e.state;
			dispatchEvent(new Event("StateChange"));
			
			if (e.state == "ready") {
				dispatchEvent(new Event("Ready"));
				}
				
		}
		
		private function bufferChange(e:BufferEvent):void 
		{
			trace ("Is buffering? " + e.buffering);
			buffering = e.buffering;
			
			dispatchEvent(new Event("BufferChange"));
		}
	
	// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	//																			SMOOTHING HACK FOR VIDEOS
	// _____________________________________________________________________________________________________________

		public function setSmoothing(element):void {
			if (element is VideoElement) {
				var videoElement:VideoElement = element as VideoElement;
				videoElement.smoothing = true;
			}
			if (element is ImageElement) {
				var imageElement:ImageElement = element as ImageElement;
				imageElement.smoothing = true;
				}
			if (element is F4MElement) {
				var f4mElement:F4MElement = element as F4MElement;
				var f4mProxied = f4mElement.proxiedElement;
				
				if (f4mProxied is VideoElement) {
					f4mProxied.smoothing = true;
					}
				}
			if (element is ProxyElement) {
				trace ("It's a proxiedElement! " + element); 
				var proxyElement:ProxyElement = element as ProxyElement;
				var proxiedElement = proxyElement.proxiedElement;
				trace ("The proxied element is: " + proxiedElement);
				
				if (proxiedElement is VAST2ImpressionProxyElement) {
					if (proxiedElement.proxiedElement is VideoElement) {
						proxiedElement.proxiedElement.smoothing = true;
						}
				}
				
				if (proxiedElement is VASTImpressionProxyElement) {
					if (proxiedElement.proxiedElement is VideoElement) {
						proxiedElement.proxiedElement.smoothing = true;
						}
				}
				
				}
		}
		
	// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	//																						LOADING ACTIONS
	// _____________________________________________________________________________________________________________
		
		
		private function onLoadingBytesChange(e:LoadEvent):void 
		{
			trace("Loading Bytes change: " + e.bytes);
			
			var cacheAmount:Number = mps.mediaPlayer.bytesLoaded / mps.mediaPlayer.bytesTotal;
			trace ("Bytes loaded: " + mps.mediaPlayer.bytesLoaded + "of" + mps.mediaPlayer.bytesTotal);
			dispatchEvent(new Event("LoadChange"));
		}
		
		private function onLoadingStateChange(e:LoadEvent):void 
		{
			trace("Loading state change: " + e.loadState);
			loadState = e.loadState;
			
			dispatchEvent(new Event("LoadChange"));
		}
		
		
	// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	//																						TIME MAPPING
	// _____________________________________________________________________________________________________________
		

		private function onCurrentTimeChange(event:TimeEvent):void
		{
			// update progress bar
			var progressAmount:Number = event.time / mps.mediaPlayer.duration;
			
			// time in seconds
			//trace("Current time: " + Math.floor(mps.mediaPlayer.currentTime) + "/" + Math.floor(mps.mediaPlayer.duration));
			
			// let's format the time correctly
			/*var currentTimeString = timeUtil.formatTime(mps.mediaPlayer.currentTime);
			var totalTimeString = timeUtil.formatTime(mps.mediaPlayer.duration);
			
			trace ("Formatted time: " +currentTimeString +"/" +totalTimeString );*/
			dispatchEvent(new Event("TimeChange"));
		}

	// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	//																				PLAY/PAUSE BEHAVIOUR
	// _____________________________________________________________________________________________________________
		
		private function onClick(event:MouseEvent):void
		{
			// toggle pause-play
			if (mps.mediaPlayer.canPause) {
			mps.mediaPlayer.playing ? mps.mediaPlayer.pause() : mps.mediaPlayer.play();
			}
		}
		
		
	// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
	//																				VAST LOAD CHANGE
	// _____________________________________________________________________________________________________________
	
		private function onVASTLoadStateChange(event:LoaderEvent):void
		{
			trace("onVASTLoadStateChange " + event.newState);
			var adElement;
			
			if(event.newState == LoadState.READY)
			{
							
				vastMediaGenerator = new VASTMediaGenerator(null, mps.mediaFactory);
				
				var vastElements:Vector.<MediaElement> = vastMediaGenerator.createMediaElements(vastLoadTrait.vastDocument, chosenPlacement);
				
				trace ("vastElements: " + vastElements
				);
				
				for each(var mediaElement:MediaElement in vastElements)
				{
					trace ("VAST media element: "+mediaElement);
					if(mediaElement is ProxyElement)
					{
						adElement = mediaElement;
					}
					if(mediaElement is CompanionElement)
						trace("Found Companion Element: " + mediaElement);
					}
				
				trace ("adElement: " + adElement);
				if (adElement != null)
				{
					mps.mediaContainer.addMediaElement(adElement);
					
					mps.mediaPlayer.media = adElement;
					setSmoothing(adElement);
				}
				else{
					trace("MediaElement not found! Check tag and placement for errors!");
					mps.mediaPlayer.media = element;
				}
			}
			
			// skip the ad in case of errors
			else if(event.newState == LoadState.LOAD_ERROR)
			{
				mps.mediaPlayer.media = element;
			}

		}
		
		public function resize(w, h):void {
			mps.width = w;
			mps.height = h;
		}
		
		
		public function clear():void {
			mps.removeEventListener(MouseEvent.CLICK, onClick);
			
			mps.mediaPlayer.removeEventListener(PlayEvent.PLAY_STATE_CHANGE, onPlayState);
			mps.mediaPlayer.removeEventListener(BufferEvent.BUFFERING_CHANGE, bufferChange);
			mps.mediaPlayer.removeEventListener(MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE, stateChange);
			
			mps.mediaPlayer.removeEventListener(TimeEvent.CURRENT_TIME_CHANGE, onCurrentTimeChange);
			mps.mediaPlayer.removeEventListener(LoadEvent.BYTES_LOADED_CHANGE, onLoadingBytesChange);
			mps.mediaPlayer.removeEventListener(LoadEvent.LOAD_STATE_CHANGE, onLoadingStateChange);
			
			mps.mediaFactory.removeEventListener(MediaFactoryEvent.PLUGIN_LOAD, onPluginLoaded);
			mps.mediaFactory.removeEventListener(MediaFactoryEvent.PLUGIN_LOAD_ERROR, onPluginLoadFailed);
			
			mps.mediaPlayer.removeEventListener ( TimeEvent.COMPLETE , onTimeComplete) ;
			
			removeChild(mps);
				
		}
	}
}